package com.party.admin.web.controller.gift;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Function;
import com.google.common.collect.Sets;
import com.party.admin.biz.file.ExcelExportService;
import com.party.admin.utils.RealmUtils;
import com.party.admin.utils.excel.ExportExcel;
import com.party.admin.web.dto.AjaxResult;
import com.party.admin.web.dto.input.common.CommonInput;
import com.party.common.paging.Page;
import com.party.common.utils.DateUtils;
import com.party.common.utils.LangUtils;
import com.party.common.utils.StringUtils;
import com.party.core.exception.BusinessException;
import com.party.core.model.coupon.Coupon;
import com.party.core.model.gift.*;
import com.party.core.service.coupon.ICouponService;
import com.party.core.service.gift.IGiftCouponService;
import com.party.core.service.gift.IGiftOrderService;
import com.party.core.service.gift.IGiftService;
import com.party.core.service.gift.IGiftTargetService;
import com.party.core.service.gift.biz.GiftBizService;
import com.party.core.utils.MyBeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Author: Administrator.
 * @Description: 礼包
 * @Date:Created in 2017/11/15 0015 上午 11:12.
 */
@Controller
@RequestMapping("gift/gift")
public class GiftController {
    @Autowired
    private IGiftService giftService;
    @Autowired
    private IGiftTargetService giftTargetService;
    @Autowired
    private IGiftCouponService giftCouponService;
    @Autowired
    private IGiftOrderService giftOrderService;
    @Autowired
    private ExcelExportService excelExportService;
    @Autowired
    private GiftBizService giftBizService;
    @Autowired
    private ICouponService couponService;

    Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 礼包列表
     *
     * @param commonInput 查询条件
     * @param gift        查询条件
     * @param page        分页
     * @return
     */
    @RequestMapping("list")
    public ModelAndView list(CommonInput commonInput, GiftListOutput gift, Page page) {
        page.setLimit(20);
        if (gift == null || gift.getProgress() == null) {
            gift.setProgress(1);
        }
        Map<String, Object> params = CommonInput.appendParams(commonInput);

        List<GiftListOutput> giftList = giftService.webListPage(gift, params, page);
        for (GiftListOutput output : giftList) {
            if (StringUtils.isNotEmpty(output.getTargetId())) {
                if (StringUtils.isEmpty(output.getTargetName())) {
                    String targetName = giftBizService.getTargetName(output.getType(), output.getTargetId());
                    output.setTargetName(targetName);
                }
            }
            Integer targetNum = giftTargetService.getCountByGiftId(output.getId());
            output.setTargetNum(targetNum);
        }
        Map<String, String> typeMap = TargetCondition.convertMap();
        ModelAndView mv = new ModelAndView("gift/giftList");
        mv.addObject("giftList", giftList);
        mv.addObject("page", page);
        mv.addObject("input", commonInput);
        mv.addObject("gift", gift);
        mv.addObject("typeMap", typeMap);
        return mv;
    }

    /**
     * 检查是否有一个众筹项目对应多个同类型的礼包
     *
     * @param targetId  项目id
     * @param type      礼包类型
     * @param condition 触发条件
     * @param giftId    礼包id
     * @return
     */
    @ResponseBody
    @RequestMapping("checkGiftUnique")
    public Boolean checkGiftUnique(String targetId, String type, String condition, String giftId) {
        List<GiftTarget> giftTargets = giftTargetService.list(new GiftTarget(type, condition, targetId, null));
        for (GiftTarget giftTarget : giftTargets) {
            if (!giftTarget.getGiftId().equals(giftId)) {
                return false;
            }
        }
        return true;

    }

    /**
     * 发布/编辑礼包
     *
     * @param giftId 礼包id
     * @return
     */
    @RequestMapping("toForm")
    public ModelAndView toForm(String giftId) throws Exception {
        ModelAndView mv = new ModelAndView("gift/giftForm");
        if (StringUtils.isNotEmpty(giftId)) {
            Gift gift = giftService.get(giftId);
            GiftListOutput listOutput = new GiftListOutput();
            MyBeanUtils.copyBeanNotNull2Bean(gift, listOutput);

            // 礼包和项目的关系
            List<GiftTarget> giftTargets = giftTargetService.findByGiftId(giftId);
            if (giftTargets.size() > 0) {
                StringBuilder builderIds = new StringBuilder();
//                StringBuilder builderNames = new StringBuilder();
                for (GiftTarget giftTarget : giftTargets) {
//                    String targetName = giftBizService.getTargetName(giftTarget.getType(), giftTarget.getTargetId());
                    builderIds.append(giftTarget.getTargetId() + ",");
//                    builderNames.append(targetName + ",");
                }

                String targetIds = giftBizService.subString(builderIds.toString());
//                String targetNames = giftBizService.subString(builderNames.toString());
                listOutput.setTargetIds(targetIds);
//                listOutput.setTargetNames(targetNames);
            }
            // 礼包和票券的关系
            if (gift.getModel().equals(Gift.MODEL_INVENTED)) {
                List<GiftCoupon> giftCoupons = giftCouponService.findByGiftId(giftId);
                if (giftCoupons.size() > 0) {
                    StringBuilder builderIds = new StringBuilder();
                    StringBuilder builderNames = new StringBuilder();

                    for (GiftCoupon giftCoupon : giftCoupons) {
                        Coupon coupon = couponService.get(giftCoupon.getCouponId());
                        builderIds.append(giftCoupon.getCouponId() + ",");
                        builderNames.append(coupon.getName() + ",");
                    }

                    String couponIds = giftBizService.subString(builderIds.toString());
                    String couponNames = giftBizService.subString(builderNames.toString());
                    listOutput.setCouponIds(couponIds);
                    listOutput.setCouponNames(couponNames);
                }
            }
            mv.addObject("gift", listOutput);
        }
        return mv;
    }

    /**
     * 礼包领取信息列表
     *
     * @param output      查询条件
     * @param commonInput 查询条件
     * @param page        分页
     * @return
     */
    @RequestMapping("giftOrderList")
    public ModelAndView giftOrderList(GiftOrderListOutput output, CommonInput commonInput, Page page) {
        page.setLimit(20);
        Map<String, Object> params = CommonInput.appendParams(commonInput);
        ModelAndView mv = new ModelAndView("gift/giftOrderList");
        if (StringUtils.isNotEmpty(output.getGiftId())) {
            Gift gift = giftService.get(output.getGiftId());
            mv.addObject("gift", gift);

            output.setModel(gift.getModel());
            List<GiftOrderListOutput> orderListOutputs = giftOrderService.webListPage(output, params, page);
            for (GiftOrderListOutput out : orderListOutputs) {
                if (StringUtils.isEmpty(out.getTargetName())) {
                    String targetName = giftBizService.getTargetName(out.getType(), out.getTargetId());
                    out.setTargetName(targetName);
                }
            }
            mv.addObject("orders", orderListOutputs);
        }

        mv.addObject("input", commonInput);
        mv.addObject("page", page);
        mv.addObject("giftOrder", output);
        return mv;
    }

    /**
     * 礼包项目列表
     *
     * @param output 查询条件
     * @param input  查询条件
     * @param page   分页
     * @return
     */
    @RequestMapping("giftTargetList")
    public ModelAndView giftTargetList(GiftTargetListOutput output, CommonInput input, Page page) {
        page.setLimit(20);
        Map<String, Object> params = CommonInput.appendParams(input);
        ModelAndView mv = new ModelAndView("gift/giftTargetList");
        if (StringUtils.isNotEmpty(output.getGiftId())) {
            Gift gift = giftService.get(output.getGiftId());
            mv.addObject("gift", gift);

            output.setType(gift.getType());
            List<GiftTargetListOutput> giftTargets = giftTargetService.webListPage(output, params, page);
            for (GiftTargetListOutput out : giftTargets) {
                if (StringUtils.isEmpty(out.getTargetName())) {
                    String targetName = giftBizService.getTargetName(out.getType(), out.getTargetId());
                    out.setTargetName(targetName);
                }
            }
            mv.addObject("targetList", giftTargets);
        }
        mv.addObject("input", input);
        mv.addObject("page", page);
        mv.addObject("giftTarget", output);
        return mv;
    }

    /**
     * 领取信息导出
     *
     * @param output      查询条件
     * @param commonInput 查询条件
     * @return
     */
    @ResponseBody
    @RequestMapping("giftOrderExport")
    public AjaxResult giftOrderExport(GiftOrderListOutput output, CommonInput commonInput) {
        try {
            Gift gift = giftService.get(output.getGiftId());
            String fileName = gift.getName() + "的领取信息.xlsx";
            Map<String, Object> params = CommonInput.appendParams(commonInput);
            List<GiftOrderListOutput> orderListOutputs = giftOrderService.webListPage(output, params, null);
            List<GiftOrderExportOutput> exportOutputs = LangUtils.transform(orderListOutputs, new Function<GiftOrderListOutput, GiftOrderExportOutput>() {
                @Override
                public GiftOrderExportOutput apply(GiftOrderListOutput input) {
                    GiftOrderExportOutput output = GiftOrderExportOutput.transfrom(input);
                    if (StringUtils.isEmpty(input.getTargetName())) {
                        String targetName = giftBizService.getTargetName(input.getType(), input.getTargetId());
                        output.setTargetName(targetName);
                    }
                    return output;
                }
            });
            ExportExcel exportExcel = new ExportExcel("", GiftOrderExportOutput.class).setDataList(exportOutputs);
            String allPath = excelExportService.getExcelPath(fileName, "gift", exportExcel);
            return AjaxResult.success((Object) allPath);
        } catch (IOException e) {
            logger.error("礼包领取信息导出异常", e);
            return AjaxResult.error("导出异常");
        }
    }

    /**
     * 保存礼包
     *
     * @param gift 礼包
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping("save")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public AjaxResult save(GiftListOutput gift, BindingResult result, String restraint, String symbol) {
        String currentId = RealmUtils.getCurrentUser().getId();
        //数据验证
        if (result.hasErrors()) {
            List<ObjectError> allErrors = result.getAllErrors();
            String description = allErrors.get(0).getDefaultMessage();
            return AjaxResult.error(description);
        }
        try {
            Long oldStock = null;
            if (StringUtils.isNotEmpty(gift.getStartDate())) {
                Date startTime = DateUtils.parse(gift.getStartDate(), "yyyy-MM-dd");
                gift.setStartTime(startTime);
            }
            if (StringUtils.isNotEmpty(gift.getEndDate())) {
                Date endTime = DateUtils.parse(gift.getEndDate(), "yyyy-MM-dd");
                gift.setEndTime(endTime);
            }
            if (gift.getModel() != null) {
                if (!gift.getModel().equals(Gift.MODEL_INVENTED)) {
                    gift.setCouponIds(null);
                }
                if (!gift.getModel().equals(Gift.MODEL_ADVERTISE)) {
                    gift.setAdvertiseUrl(null);
                }
            }
            if (gift.getCondition().equals(TargetCondition.ZC_APPLY.getCode()) || gift.getCondition().equals(TargetCondition.ZC_SUCCESS.getCode())) {
                gift.setConditionParams(null);
            } else {
                String conditionParams = restraint + " " + symbol + " " + gift.getConditionParams();
                gift.setConditionParams(conditionParams);
            }
            if (StringUtils.isEmpty(gift.getId())) {
                gift.setCreateBy(currentId);
                gift.setUpdateBy(currentId);
                giftService.insert(gift);
            } else {
                Gift dbGift = giftService.get(gift.getId());
                oldStock = dbGift.getStock();
                dbGift.setUpdateBy(currentId);
                MyBeanUtils.copyBean2Bean(dbGift, gift);
                giftService.update(dbGift);

                MyBeanUtils.copyBeanNotNull2Bean(dbGift, gift);
            }
            giftBizService.saveOrUpdateWithTarget(gift.getTargetIds(), gift);
            giftBizService.saveOrUpdateWithCoupon(gift.getCouponIds(), gift, oldStock);
            return AjaxResult.success();
        } catch (BusinessException e) {
            logger.error(e.getMessage(), e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            logger.error("礼包保存失败", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("");
        }
    }

    /**
     * 删除礼包
     *
     * @param giftId 礼包id
     * @return
     */
    @ResponseBody
    @RequestMapping("delete")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public AjaxResult delete(String giftId) {
        if (StringUtils.isEmpty(giftId)) {
            return AjaxResult.error("id不能为空");
        }
        try {
            List<GiftOrder> giftOrders = giftOrderService.list(new GiftOrder("", giftId, ""));
            if (giftOrders.size() > 0) {
                return AjaxResult.error("该礼包已有人领取，不能删除");
            } else {
                List<GiftTarget> giftTargets = giftTargetService.findByGiftId(giftId);
                if (giftTargets.size() > 0) {
                    return AjaxResult.error("该礼包已分配给项目，不能删除");
                }
            }
            giftOrderService.deleteByGiftId(giftId);
            giftTargetService.deleteByGiftId(giftId);
            giftCouponService.deleteByGiftId(giftId);
            giftService.delete(giftId);
            return AjaxResult.success();
        } catch (Exception e) {
            logger.error("删除礼包异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error("删除异常");
        }
    }

    /**
     * 移除项目和礼包的关系
     *
     * @param giftId   礼包id
     * @param targetId 项目id
     * @return
     */
    @ResponseBody
    @RequestMapping("removeTarget")
    public AjaxResult removeTarget(String giftId, String targetId) {
        if (StringUtils.isEmpty(giftId) || StringUtils.isEmpty(targetId)) {
            return AjaxResult.error("信息不完整，不能解除关系");
        }
        GiftOrder giftOrder = new GiftOrder();
        giftOrder.setTargetId(targetId);
        giftOrder.setGiftId(giftId);
        List<GiftOrder> giftOrders = giftOrderService.list(giftOrder);
        if (giftOrders.size() > 0) {
            return new AjaxResult(false, "该项目已经有领取信息，不能解除关系");
        }
        giftTargetService.deleteByUnique(new GiftTarget(targetId, giftId));
        return AjaxResult.success();
    }

    /**
     * 选择礼包
     *
     * @param type    礼包类型
     * @param name    礼包名称
     * @param giftIds 已选的礼包ids
     * @param page    分页
     * @return
     */
    @RequestMapping("{type}/selectGift")
    public ModelAndView selectGift(@PathVariable(value = "type") String type, String name, String giftIds,
                                   Page page, String targetId, Integer progress) {
        page.setLimit(5);
        ModelAndView mv = new ModelAndView("gift/selectGift");
        Gift output = new Gift();
        output.setType(type);
        output.setName(name);
        output.setProgress(progress);
        if (output.getProgress() == null) {
            output.setProgress(1);
        }
        List<Gift> giftList = giftService.listPage(output, page);
        mv.addObject("giftList", giftList);
        mv.addObject("page", page);
        mv.addObject("giftOutput", output);
        mv.addObject("giftIds", giftIds);
        mv.addObject("targetId", targetId);
        Set<String> ids = Sets.newHashSet(giftIds.split(","));
        List<Gift> gifts = giftService.batchList(ids, new Gift(), null);
        List<Gift> myGiftIds = LangUtils.transform(gifts, new Function<Gift, Gift>() {
            @Override
            public Gift apply(Gift input) {
                Gift newGift = new Gift();
                newGift.setId(input.getId());
                newGift.setName(input.getName());
                newGift.setCondition(input.getCondition());
                return newGift;
            }
        });
        mv.addObject("giftsJson", JSONObject.toJSONString(myGiftIds));
        mv.addObject("giftListJson", JSONObject.toJSONString(giftList));
        return mv;
    }

    /**
     * 根据项目id和类型获取礼包
     *
     * @param targetId
     * @param type
     * @return
     */
    @ResponseBody
    @RequestMapping("{type}/findByTargetId")
    public List<Gift> findByTargetId(String targetId, @PathVariable(value = "type") String type) {
        List<Gift> gifts = giftService.findByTargetId(targetId, type);
        return gifts;
    }

    /**
     * 保存项目和礼包的关系
     *
     * @param targetId 项目id
     * @param giftIds  礼包id集合
     * @return
     */
    @ResponseBody
    @RequestMapping("saveGiftTarget")
    public AjaxResult saveGiftTarget(String targetId, String giftIds) {
        if (StringUtils.isEmpty(targetId)) {
            return AjaxResult.error("信息不完全，不能保存");
        }
        try {
            /************* 礼包和项目的关系 ****************/
            giftBizService.saveOrUpdateWithTarget(giftIds, targetId);
            return AjaxResult.success();
        } catch (Exception e) {
            logger.error("保存项目和礼包的关系异常", e);
            return AjaxResult.error("保存失败");
        }
    }

    /**
     * 初始化
     */
    @ResponseBody
    @RequestMapping("initTargetName")
    public AjaxResult initTargetName() {
        List<GiftOrder> giftOrders = giftOrderService.list(new GiftOrder());
        for (GiftOrder giftOrder : giftOrders) {
            String targetName = giftBizService.getTargetName(giftOrder.getType(), giftOrder.getTargetId());
            if (StringUtils.isNotEmpty(targetName)) {
                GiftOrder db = giftOrderService.get(giftOrder.getId());
                db.setTargetName(targetName);
                giftOrderService.update(db);
            }
        }
        return AjaxResult.success();
    }
}
